
#include <SDL.h>
#include <time.h>
#include "config.h"
#include "map.h"

extern SDL_Surface *screen;
extern SDL_Surface *tiles;
extern SDL_Surface *path_surface;
extern SDL_Surface *path_end_surface;

int war_map[MAP_COLS * MAP_ROWS];

#define LEFT_ARROW        0
#define RIGHT_ARROW       1
#define UP_ARROW          2
#define DOWN_ARROW        3
#define UPLEFT_ARROW      4
#define UPRIGHT_ARROW     5
#define DOWNLEFT_ARROW    6
#define DOWNRIGHT_ARROW   7

SDL_Rect path_frames[8] = {{0, 0, 64, 32}, {0, 32, 64, 32},
                           {64, 0, 32, 64}, {96, 0, 32, 64},
                           {128, 0, 64, 64}, {192, 0, 64, 64},
                           {256, 0, 64, 64}, {320, 0, 64, 64}};

Pos UpLeftPos(int grid1, int grid2)
{
    int x1, y1, x2, y2;
    Pos pos;

    x1 = grid1 % MAP_COLS;
    y1 = grid1 / MAP_COLS;
    x2 = grid2 % MAP_COLS;
    y2 = grid2 / MAP_COLS;
    pos.x = min(x1, x2) * TILE_WIDTH + MAP_OFFSETX;
    pos.y = min(y1, y2) * TILE_HEIGHT + MAP_OFFSETY;
    return pos;
}

char ArrowType(int from_grid, int to_grid)
{
    int x1, y1, x2, y2;
    x1 = from_grid % MAP_COLS;
    y1 = from_grid / MAP_COLS;
    x2 = to_grid % MAP_COLS;
    y2 = to_grid / MAP_COLS;

    if(x1 < x2) {
        if (y1 < y2) 
            return DOWNRIGHT_ARROW;
        else if (y1 == y2)
            return RIGHT_ARROW;
        else
            return UPRIGHT_ARROW;
    }
    else if(x1 > x2){
        if (y1 < y2)
            return DOWNLEFT_ARROW;
        else if (y1 == y2)
            return LEFT_ARROW;
        else
            return UPLEFT_ARROW;
    }
    else {
        if (y1 < y2)
            return DOWN_ARROW;
        else
            return UP_ARROW;
    }
}

void DrawPathArrow(int from, int to)
{
    char arrow_type;
    SDL_Rect src_rect, dest_rect;
    Pos up_left_draw;

    arrow_type = ArrowType(from, to);
    src_rect = path_frames[arrow_type];

    up_left_draw = UpLeftPos(from, to);
    dest_rect.x = up_left_draw.x;
    dest_rect.y = up_left_draw.y;
    dest_rect.w = src_rect.w;
    dest_rect.h = src_rect.h;

    SDL_BlitSurface(path_surface, &src_rect,
                    screen, &dest_rect);
}

void DrawPathEnd(int grid)
{
    int x, y;
    SDL_Rect dest_rect;

    x = grid % MAP_COLS * TILE_WIDTH + MAP_OFFSETX;
    y = grid / MAP_COLS * TILE_HEIGHT + MAP_OFFSETY;
    dest_rect.x = x;
    dest_rect.y = y;
    dest_rect.w = TILE_WIDTH;
    dest_rect.h = TILE_HEIGHT;

    SDL_BlitSurface(path_end_surface, NULL,
                    screen, &dest_rect);
}

void DrawPath(int path[], int start)
{
    int i = 0;
    while(path[i] > 0) {
        if(i > 0)
            DrawPathArrow(path[i - 1], path[i]);
        else
            DrawPathArrow(start, path[i]);
        i ++;
    }
    if(i > 0)
        DrawPathEnd(path[i - 1]);
}

void MapGenerate()
{
    int i;
    int grid_num = MAP_COLS * MAP_ROWS;
    for (i = 0; i < grid_num; i ++) {
        war_map[i] = FLOOR_GLYPH;
    }

    srand(time(NULL));
    
    // create trees
    int tree_num = grid_num / 5;
    int allocated_tree_num = 0;
    int grid_idx;
    while(allocated_tree_num < tree_num){
        grid_idx = rand() % grid_num;
        if (war_map[grid_idx] == FLOOR_GLYPH) {
            war_map[grid_idx] = TREE_GLYPH;
            allocated_tree_num ++;
        }
    }
}

char MapBlock(char x, char y)
{
    int grid_idx = y * MAP_COLS + x;
    if(war_map[grid_idx] == TREE_GLYPH)
        return 1;
    if(x < 0 || x >= MAP_COLS || y < 0 || y >= MAP_ROWS)
        return 1;
    return 0;
}

void MapDraw(ClipRect r)
{
    /* printf("map redraw: %d,%d %d,%d\n", */
    /*       r.startX, r.startY, r.endX, r.endY); */

    char i, j;
    int glyph_idx;
    SDL_Rect src_rect, dest_rect;

    src_rect.w = dest_rect.w = TILE_WIDTH;
    src_rect.h = dest_rect.h = TILE_HEIGHT;

    for(i = r.startY; i <= r.endY; ++ i) {
        for(j = r.startX; j <= r.endX; ++ j){
            glyph_idx = war_map[i * MAP_COLS + j];
            src_rect.x = glyph_idx % TILE_COLS * TILE_WIDTH;
            src_rect.y = glyph_idx / TILE_COLS * TILE_HEIGHT;
            
            dest_rect.x = MAP_OFFSETX + j * TILE_WIDTH;
            dest_rect.y = MAP_OFFSETY + i * TILE_HEIGHT;
            SDL_BlitSurface(tiles, &src_rect, screen, &dest_rect);
        }
    }
}
